package com.change.core.web.request;

import cn.hutool.core.util.IdUtil;
import com.change.core.dto.Account;
import com.change.core.redis.Redis;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * AccountContext
 *
 * @author 坏孩子是你啊
 * @date 2021/9/16 2:57 下午
 */
@Slf4j
@Component
public class AccountContext {

    private static final ThreadLocal<Session> SESSION = new ThreadLocal<>();

    // token过期时间为3天
    private static final long tokenTimeout = 86400 * 3;

    /**
     * 获取当前登录的账号ID
     *
     * @return
     */
    public static Integer getAccountId() {
        if(null == SESSION.get()){
            log.error("当前用户会话无效");
            return 0;
        }
        return SESSION.get().getAccountId();
    }

    public static String storeSession(Account account) {
        String token = IdUtil.fastSimpleUUID();
        Session session = new Session(account.getId(), account.getAccount(), token, 0);

        Redis.set(getTokenKey(token), session.getFields(), tokenTimeout);
        Redis.set(getAccountIdTokenKey(account.getId()), token, tokenTimeout);
        return token;
    }

    public static void removeSession(Integer appUserId) {
        String appUserIdTokenKey = getAccountIdTokenKey(appUserId);
        String token = Redis.get(appUserIdTokenKey);
        if (Objects.nonNull(token)) {
            Redis.remove(getTokenKey(token), appUserIdTokenKey);
        }
    }

    public static void expireSession() {
        Session session = SESSION.get();
        Redis.expire(getTokenKey(session.getToken()), tokenTimeout);
        Redis.expire(getAccountIdTokenKey(session.getAccountId()), tokenTimeout);
    }

    public static boolean initThreadSession(String token) {
        Map<String, Object> fields = Redis.get(getTokenKey(token));

        if (fields == null) {
            return false;
        } else {
            SESSION.set(new Session(fields));
            expireSession();
            return true;
        }
    }

    public static void clearThreadSession() {
        SESSION.remove();
    }

    private static String getAccountIdTokenKey(Integer accountId) {
        return "account:" + accountId;
    }

    private static String getTokenKey(String token) {
        return "token:" + token;
    }

    @Getter
    static class Session {
        private Integer accountId;
        private String accountName;
        private String token;
        private Integer companyId;

        public Session(Map<String, Object> fields) {
            this.accountId = (Integer) fields.get("accountId");
            this.accountName = (String) fields.get("accountName");
            this.token = (String) fields.get("token");
            this.companyId = (Integer) fields.get("companyId");
        }

        public Session(Integer accountId, String accountName, String token, Integer companyId) {
            this.accountId = accountId;
            this.accountName = accountName;
            this.token = token;
            this.companyId = companyId;
        }

        public Map<String, Object> getFields() {
            Map<String, Object> fields = new HashMap<>();
            fields.put("accountId", this.accountId);
            fields.put("accountName", this.accountName);
            fields.put("token", this.token);
            fields.put("companyId", this.companyId);
            return fields;
        }
    }
}
